﻿/*
 * MIT License
 *Copyright (c) 2021 易开元(Easy-Open-Meta)

 *Permission is hereby granted, free of charge, to any person obtaining a copy
 *of this software and associated documentation files (the "Software"), to deal
 *in the Software without restriction, including without limitation the rights
 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *copies of the Software, and to permit persons to whom the Software is
 *furnished to do so, subject to the following conditions:

 *The above copyright notice and this permission notice shall be included in all
 *copies or substantial portions of the Software.

 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *SOFTWARE.
 *
 */
using EOM.TSHotelManagement.Common.Contract;
using EOM.TSHotelManagement.Common.Core;
using EOM.TSHotelManagement.Common.Util;
using EOM.TSHotelManagement.EntityFramework;
using jvncorelib.EncryptorLib;
using jvncorelib.EntityLib;
using SqlSugar;
using System.Security.Claims;

namespace EOM.TSHotelManagement.Application
{
    /// <summary>
    /// 管理员数据访问层
    /// </summary>
    public class AdminService : IAdminService
    {
        /// <summary>
        /// 管理员
        /// </summary>
        private readonly GenericRepository<Administrator> adminRepository;

        /// <summary>
        /// 管理员类型
        /// </summary>
        private readonly GenericRepository<AdministratorType> adminTypeRepository;

        /// <summary>
        /// 数据保护
        /// </summary>
        private readonly DataProtectionHelper dataProtector;

        /// <summary>
        /// 加密
        /// </summary>
        private readonly EncryptLib encrypt;

        /// <summary>
        /// JWT加密
        /// </summary>
        private readonly JWTHelper jWTHelper;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="adminRepository"></param>
        /// <param name="adminTypeRepository"></param>
        /// <param name="dataProtectionProvider"></param>
        /// <param name="encrypt"></param>
        /// <param name="jWTHelper"></param>
        public AdminService(GenericRepository<Administrator> adminRepository, GenericRepository<AdministratorType> adminTypeRepository, DataProtectionHelper dataProtectionProvider, EncryptLib encrypt, JWTHelper jWTHelper)
        {
            this.adminRepository = adminRepository;
            this.adminTypeRepository = adminTypeRepository;
            this.dataProtector = dataProtectionProvider;
            this.encrypt = encrypt;
            this.jWTHelper = jWTHelper;
        }

        /// <summary>
        /// 后台系统登录
        /// </summary>
        /// <param name="readAdministratorInputDto"></param>
        /// <returns></returns>
        public SingleOutputDto<ReadAdministratorOutputDto> Login(ReadAdministratorInputDto readAdministratorInputDto)
        {
            if (readAdministratorInputDto == null)
            {
                throw new ArgumentNullException(nameof(readAdministratorInputDto));
            }

            var existingAdmin = adminRepository.GetFirst(a => a.Account == readAdministratorInputDto.Account);

            if (existingAdmin == null)
            {
                return null;
            }

            if (existingAdmin.IsDelete == 1)
            {
                return null;
            }


            var encrtptPwd = string.Empty;
            try
            {
                encrtptPwd = encrypt.Encryption(readAdministratorInputDto.Password, EncryptionLevel.Enhanced);
                var passed = encrypt.Compare(encrtptPwd, existingAdmin.Password);
                if (!passed)
                {
                    return null;
                }
            }
            catch (Exception)
            {
                var originalPwd = dataProtector.DecryptAdministratorData(readAdministratorInputDto.Password);
                var currentPwd = dataProtector.DecryptAdministratorData(existingAdmin.Password);
                var passed = originalPwd == currentPwd;
                if (!passed)
                {
                    return null;
                }
            }

            if (encrtptPwd.IsNullOrEmpty() || existingAdmin.Password.IsNullOrEmpty())
            {
                return null;
            }

            existingAdmin.Password = string.Empty;
            existingAdmin.UserToken = jWTHelper.GenerateJWT(new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, existingAdmin.Name),
                new Claim(ClaimTypes.SerialNumber, existingAdmin.Number)
            }));

            var source = EntityMapper.Map<Administrator, ReadAdministratorOutputDto>(existingAdmin);

            return new SingleOutputDto<ReadAdministratorOutputDto>
            {
                Data = source
            };
        }

        /// <summary>
        /// 获取所有管理员列表
        /// </summary>
        /// <returns></returns>
        public ListOutputDto<ReadAdministratorOutputDto> GetAllAdminList(ReadAdministratorInputDto readAdministratorInputDto)
        {
            var where = Expressionable.Create<Administrator>();

            if (!readAdministratorInputDto.IsDelete.IsNullOrEmpty())
            {
                where = where.And(a => a.IsDelete == readAdministratorInputDto.IsDelete);
            }

            var count = 0;
            List<Administrator> administrators = new List<Administrator>();

            if (!readAdministratorInputDto.IgnorePaging && readAdministratorInputDto.Page != 0 && readAdministratorInputDto.PageSize != 0)
            {
                administrators = adminRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readAdministratorInputDto.Page, readAdministratorInputDto.PageSize, ref count);
            }
            else
            {
                administrators = adminRepository.AsQueryable().Where(where.ToExpression()).ToList();
                count = administrators.Count;
            }

            administrators.ForEach(admin =>
            {
                var type = adminTypeRepository.GetFirst(a => a.TypeId == admin.Type);
                admin.TypeName = type?.TypeName ?? "";
                admin.IsSuperAdminDescription = admin.IsSuperAdmin == 1 ? "是" : "否";
            });

            var result = EntityMapper.MapList<Administrator, ReadAdministratorOutputDto>(administrators);

            return new ListOutputDto<ReadAdministratorOutputDto>
            {
                Data = new PagedData<ReadAdministratorOutputDto>
                {
                    Items = result,
                    TotalCount = count
                }
            };
        }

        /// <summary>
        /// 添加管理员
        /// </summary>
        /// <param name="createAdministratorInputDto"></param>
        /// <returns></returns>
        public BaseResponse AddAdmin(CreateAdministratorInputDto createAdministratorInputDto)
        {
            try
            {
                var haveSuperAdmin = adminRepository.IsAny(a => a.IsSuperAdmin == createAdministratorInputDto.IsSuperAdmin && a.IsDelete != 1);
                if (haveSuperAdmin)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Super Administrator already exists", "超级管理员已存在"), Code = BusinessStatusCode.InternalServerError };
                }
                var haveAdmin = adminRepository.IsAny(a => a.Account == createAdministratorInputDto.Account);
                if (haveAdmin)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Administrator already exists", "管理员已存在"), Code = BusinessStatusCode.InternalServerError };
                }

                createAdministratorInputDto.Password = dataProtector.EncryptAdministratorData(createAdministratorInputDto.Password);
                var admin = EntityMapper.Map<CreateAdministratorInputDto, Administrator>(createAdministratorInputDto);
                var result = adminRepository.Insert(admin);
                if (!result)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Add Administrator Failed", "添加管理员失败"), Code = BusinessStatusCode.InternalServerError };
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 更新管理员
        /// </summary>
        /// <param name="updateAdministratorInputDto"></param>
        /// <returns></returns>
        public BaseResponse UpdAdmin(UpdateAdministratorInputDto updateAdministratorInputDto)
        {
            try
            {
                updateAdministratorInputDto.Password = dataProtector.EncryptAdministratorData(updateAdministratorInputDto.Password);
                var admin = EntityMapper.Map<UpdateAdministratorInputDto, Administrator>(updateAdministratorInputDto);
                var result = adminRepository.Update(admin);
                if (!result)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Update Administrator Failed", "更新管理员失败"), Code = BusinessStatusCode.InternalServerError };
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 删除管理员
        /// </summary>
        /// <param name="deleteAdministratorInputDto"></param>
        /// <returns></returns>
        public BaseResponse DelAdmin(DeleteAdministratorInputDto deleteAdministratorInputDto)
        {
            try
            {
                var isSuperAdmin = adminRepository.IsAny(a => a.Number == deleteAdministratorInputDto.Number && a.IsSuperAdmin == 1);
                if (isSuperAdmin)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Super Administrator cannot be deleted", "超级管理员无法删除"), Code = BusinessStatusCode.InternalServerError };
                }
                adminRepository.SoftDelete(EntityMapper.Map<DeleteAdministratorInputDto, Administrator>(deleteAdministratorInputDto));
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 获取所有管理员类型
        /// </summary>
        /// <returns></returns>
        public ListOutputDto<ReadAdministratorTypeOutputDto> GetAllAdminTypes(ReadAdministratorTypeInputDto readAdministratorTypeInputDto)
        {
            var where = Expressionable.Create<AdministratorType>();

            if (!readAdministratorTypeInputDto.IsDelete.IsNullOrEmpty())
            {
                where = where.And(a => a.IsDelete == readAdministratorTypeInputDto.IsDelete);
            }

            var count = 0;
            List<AdministratorType> administratorTypes = new List<AdministratorType>();

            if (!readAdministratorTypeInputDto.IgnorePaging && readAdministratorTypeInputDto.Page != 0 && readAdministratorTypeInputDto.PageSize != 0)
            {
                administratorTypes = adminTypeRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readAdministratorTypeInputDto.Page, readAdministratorTypeInputDto.PageSize, ref count);
            }
            else
            {
                administratorTypes = adminTypeRepository.AsQueryable().Where(where.ToExpression()).ToList();
                count = administratorTypes.Count;
            }

            var result = EntityMapper.MapList<AdministratorType, ReadAdministratorTypeOutputDto>(administratorTypes);

            return new ListOutputDto<ReadAdministratorTypeOutputDto>
            {
                Data = new PagedData<ReadAdministratorTypeOutputDto>
                {
                    Items = result,
                    TotalCount = count
                }
            };
        }

        /// <summary>
        /// 添加管理员类型
        /// </summary>
        /// <param name="createAdministratorTypeInputDto"></param>
        /// <returns></returns>
        public BaseResponse AddAdminType(CreateAdministratorTypeInputDto createAdministratorTypeInputDto)
        {
            try
            {
                adminTypeRepository.Insert(EntityMapper.Map<CreateAdministratorTypeInputDto, AdministratorType>(createAdministratorTypeInputDto));
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 更新管理员类型
        /// </summary>
        /// <param name="updateAdministratorTypeInputDto"></param>
        /// <returns></returns>
        public BaseResponse UpdAdminType(UpdateAdministratorTypeInputDto updateAdministratorTypeInputDto)
        {
            try
            {
                adminTypeRepository.Update(EntityMapper.Map<UpdateAdministratorTypeInputDto, AdministratorType>(updateAdministratorTypeInputDto));
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 删除管理员类型
        /// </summary>
        /// <param name="deleteAdministratorTypeInputDto"></param>
        /// <returns></returns>
        public BaseResponse DelAdminType(DeleteAdministratorTypeInputDto deleteAdministratorTypeInputDto)
        {
            try
            {
                var adminType = adminTypeRepository.GetFirst(a => a.TypeId == deleteAdministratorTypeInputDto.TypeId);
                adminType.IsDelete = deleteAdministratorTypeInputDto.IsDelete;
                adminTypeRepository.SoftDelete(adminType);
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }
    }
}
